package org.example.core.controller;

import org.example.core.enums.ApiResult;
import org.example.core.exception.ErrorException;
import org.example.core.model.SupperModel;
import org.example.core.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Map;

public class BaseController<I, S extends BaseService, M extends SupperModel<I>> extends Controller {

    @Autowired
    private S service;

    @GetMapping("/searchAll")
    public ApiResult searchAll() {
        return ApiResult.success(service.searchAll());
    }

    @GetMapping("/getById")
    public ApiResult getById(@RequestParam I id) {
        return ApiResult.success(service.getById(id));
    }

    @PostMapping("/update")
    public ApiResult update(@RequestBody M model) {
        Object id = model.getId();
        if (ObjectUtils.isEmpty(id)) {
            throw new ErrorException("主键id不能为空");
        }
        return ApiResult.success(service.update(model));
    }

    @PostMapping("/delete")
    public ApiResult delete(@RequestParam I id) {
        return ApiResult.success(service.delete(id));
    }

    @PostMapping("/add")
    public ApiResult add(@RequestBody M model) {
        return ApiResult.success(service.add(model));
    }

    @GetMapping("/searchPage")
    public ApiResult searchPage(@RequestParam(defaultValue = "1") int page,
                                @RequestParam(defaultValue = "10") int limit,
                                @RequestParam(required = false) Map<String,Object> params) {
        return ApiResult.success(service.searchPage(page, limit));
    }

    private M convertMapToModel(Map<String, Object> params) {
        try {
            M result = getModelClass().newInstance();
            for (Class modelClass = result.getClass(); !Object.class.equals(modelClass); modelClass = modelClass.getSuperclass()) {
                Field[] fields = modelClass.getDeclaredFields();
                Arrays.stream(fields).forEach(field -> {
                    field.setAccessible(true);
                    try {
                        field.set(result, params.get(field.getName()));
                    } catch (IllegalAccessException e) {
                        throw new ErrorException(e);
                    }
                });
            }
            return result;
        } catch (Exception e) {
            throw new ErrorException(e);
        }
    }

    private Class<M> getModelClass() {
        Class<M> modelClass = null;
        Type genericSuperclass = getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
            modelClass = (Class<M>) actualTypeArguments[2];
        }
        return modelClass;
    }
}